// 交叉类型和联合类型

interface DogInterface {
  run(): void;
}

interface CatInterface {
  jump(): void;
}

let pet: DogInterface & CatInterface = {
  run: function () {}, // 需要实现接口的方法
  jump: function () {},
}; // 宠物，交叉类型用 & 符来连接

// 联合类型和字面量联合类型

let a: number | string = 1;
let b: "a" | "b" | "c" = "c";
let c: 1 | 2 | 3 = 1;

// 对象联合类型

class Dog implements DogInterface {
  run() {}
  eat() {}
}

class Cat implements CatInterface {
  jump() {}
  eat() {}
}

enum Master {
  Boy,
  Girl,
}

function getPet(master: Master) {
  let pet = master === Master.Boy ? new Dog() : new Cat();
  // 下面呢我们想调用下这个实例的方法
  pet.eat();
  // pet.run(); // 这是不能访问的
  return pet;
}

interface Square {
  kind: "square";
  size: number;
}

interface Rectangle {
  kind: "rectangle";
  width: number;
  height: number;
}

// 新加的 shape
interface Circle {
  kind: "circle";
  r: number;
}

type Shape = Square | Rectangle | Circle; // 然后呢我们把 Circle 加入到这个联合类型中
function area(s: Shape) {
  switch (s.kind) {
    case "square":
      return s.size * s.size; // 那么在这个区块种呢我们就可以访问 square 的属性
    case "rectangle":
      return s.height * s.width; // 那么在这个区块中呢我们就可以访问 rectangle 的属性
    case "circle":
      return Math.PI * s.r ** 2;
    default:
      return ((e: never) => {
        throw new Error(e);
      })(s);
  }
}

console.log(area({ kind: "circle", r: 1 }));

export {};
